package destiny.预测;

import java.util.Map;

import destiny.五行.五行;

public class 运神 {

	/**
	 * 在四柱命局中，日旺与否在很大程度上看阴令对日干来说处于什么状态，日干生在旺月为得令，但如果不得地，不得生、助，势必克泄耗大于生助，则旺而不旺了。
	 * 日干处在衰月为失令，如果生助多而旺，则弱而不弱了。
	 * 
	 * 身旺的判断条件。
	 * 
	 * 得令：日干旺于月支，处长生、沐浴、冠带、临官、帝旺之地为得论。 天干生旺死绝已计算
	 * 
	 * 得地：日干在其余各支中得长生（须阳日干）、禄刃（支中藏干的本气为比，为劫），或逢墓库（阳日干逢墓库为有根，阴日干无气，故无根）。天干生旺死绝已计算
	 * 
	 * 得生：日干得四柱干支中的正偏印之生为得生。干支生克计算时已暗含
	 * 
	 * 得助：日干与四柱其他天干同类为逢比肩劫财帮身，此为得助。干支生克计算时已暗含
	 * 
	 * 首先，日干得令是判断身旺最重要的方面；
	 * 
	 * 其次，在得令的前提下，得地、得生或得助再占其一，可以肯定是身旺。占其二为偏旺偏强。三者都占，就为过旺至极；
	 * 
	 * 其三，在不得令的情况下，得地、得生或得助占其二项以上，要有力又多助益，为身旺或偏旺；
	 * 
	 * 其四，在不得令的情况下，得地、得生或得助只占一项，但四柱中三合局或在三会局为生身之印局，或为帮日干之身的比局，为身旺；
	 * 
	 * 其五，在不得令的情况下，如果得地、得生或得助有力且众，虽占二项仍为身旺，但如果地中长生、禄、刃、墓中占的成分少，势必地支中克我，耗我，
	 * 泄我的成分就多。日干便处于较平衡的不旺不弱之间，不易定出旺衰，用神就不好找，走什么运更好就无从论起。
	 * 
	 * 在这种情况下：
	 * 
	 * 1，如果天干化合和五行或地支合化的五行是生身帮身，就为身旺；是克制我，耗我气和泄我气的，便为身弱。
	 * 
	 * 2， 地支半合或半会生身帮身五行的，也为身旺，反之为弱。
	 * 
	 * 3 ，克我，耗我或泄我之气的处在弱地（不得令），而生我，帮我之气的处在旺地，则为身旺，反之不弱；
	 * 
	 * 4 ，克我、耗我或泄我的干支逢冲、被制服、被合去，或离得远，仍为身旺，反之为弱。
	 * 
	 * 计算五行强弱，求平衡。
	 * 
	 * 日弱 官杀多 取印星 取比劫
	 * 
	 * 日弱 财星多 取比劫 取印星
	 * 
	 * 日弱 食伤多 取印星 取比劫
	 * 
	 * 日强 印星多 取财星 官杀食伤
	 * 
	 * 日强 比劫多 取官杀 取食伤 取财星
	 * 
	 * 财星与印星旺而相战，有一点官杀星可通关。
	 * 
	 * 印枭与伤食旺而相战，日干得令可通关。
	 * 
	 * 官杀与比劫旺而相战，有一点印星可通关。
	 * 
	 * 火多太燥，喜水调候，以免太过干燥偏枯
	 * 
	 * 水多太冷，喜火调候，以免太过寒冷偏枯
	 * 
	 * FIXME: 支中藏干余气不论 (TBD!!!)
	 */
	public static 运神 日干求神(干支数[] 四柱数) {
		Map<五行, Integer> weights = Utils.五行用神数(四柱数);
		干数 日数 = 四柱数[Consts.四柱日序].干数();
		五行 日主 = 日数.术数().五行(), 月提 = 四柱数[Consts.四柱月序].支数().术数().五行();
		if (日数.getWeight() < Consts.强旺阀值) {
			// 日弱
			int w1 = weights.containsKey(日主.官()) ? weights.get(日主.官()) : 0, w2 = weights
					.containsKey(日主.克()) ? weights.get(日主.克()) : 0, w3 = weights
					.containsKey(日主.生()) ? weights.get(日主.生()) : 0;
			/*
			 * 日弱 官杀多 取印星 取比劫
			 */
			if (w1 > Consts.强旺阀值 && w1 > w2 && w1 > w3) {
				return new 运神(日主.印(), 日主);
			}
			/*
			 * 日弱 财星多 取比劫 取印星
			 */
			if (w2 > Consts.强旺阀值 && w2 > w1 && w2 > w3) {
				return new 运神(日主, 日主.印());
			}
			/*
			 * 日弱 食伤多 取印星 取比劫
			 */
			if (w3 > Consts.强旺阀值 && w3 > w1 && w3 > w2) {
				return new 运神(日主.印(), 日主);
			}
		} else {
			// 日强
			int w1 = weights.containsKey(日主.印()) ? weights.get(日主.印()) : 0, w2 = weights
					.containsKey(日主) ? weights.get(日主) : 0;
			/*
			 * 日强 比劫多 取官杀 取食伤 取财星
			 */
			if (w1 > Consts.强旺阀值 && w1 > w2) {
				return new 运神(日主.克(), 日主.生());
			}
			/*
			 * 日强 比劫多 取官杀 取食伤 取财星
			 */
			if (w2 > Consts.强旺阀值 && w2 > w1) {
				return new 运神(日主.官(), 日主.生(), 日主.克());
			}

			/*
			 * 火多太燥，喜水调候，以免太过干燥偏枯
			 * 
			 * 水多太冷，喜火调候，以免太过寒冷偏枯
			 */
			// 调候
			if (五行.水.equals(日主) && 五行.水.equals(月提)) {
				return new 运神(五行.火);
			} else if (五行.火.equals(日主) && 五行.火.equals(月提)) {
				return new 运神(五行.水);
			}
		}
		/*
		 * 财星与印星旺而相战，有一点官杀星可通关。
		 */
		if (weights.containsKey(日主.克()) && weights.containsKey(日主.印())
				&& weights.get(日主.克()) > Consts.强旺阀值
				&& weights.get(日主.印()) > Consts.强旺阀值) {
			return new 运神(日主.官());
		}
		/*
		 * 印枭与伤食旺而相战，日干得令可通关。此处取比劫。
		 */
		if (weights.containsKey(日主.生()) && weights.containsKey(日主.印())
				&& weights.get(日主.生()) > Consts.强旺阀值
				&& weights.get(日主.印()) > Consts.强旺阀值) {
			return new 运神(日主);
		}
		/*
		 * 官杀与比劫旺而相战，有一点印星可通关。
		 */
		if (weights.containsKey(日主.官()) && weights.containsKey(日主)
				&& weights.get(日主.官()) > Consts.强旺阀值
				&& weights.get(日主) > Consts.强旺阀值) {
			return new 运神(日主.印());
		}

		return new 运神(日主.印());
	}

	private 五行[] 用神;

	public 运神(五行... 用神) {
		if (用神.length > 1)
			this.用神 = 用神;
		else
			this.用神 = new 五行[] { 用神[0], 用神[0].印() };
	}

	public 五行[] 用神集() {
		return 用神;
	}

	public 五行 用神() {
		return 用神[0];
	}

	public 五行 喜神() {
		return 用神[1];
	}

	/**
	 * 唯一情况，日强 比劫多 取官杀 取食伤 取财星
	 */
	public 五行 喜神2() {
		if (用神.length > 2)
			return 用神[2];
		else
			return null;
	}

	/*
	 * 凶神为忌神，凡刑冲克害合去用神或损害喜神的，即为忌神。
	 */
	public 五行 忌神() {
		// 凡刑冲克害合去用神，局中论
		// 损害喜神的，即为忌神。
		return 喜神().官();
	}

}
